import UtilFuncs from '../common/tools/utilfuncs.js'
var funcs = UtilFuncs.UtilFuncs;

import GlobalConst from '../common/globalConst.js'
var global = GlobalConst.GlobalConst;
import LGXCOM from '../common/common.js'

import {LGXEnums}  from '../common/sysenum.js';


import { GlobalVar } from '../common/globalvar.js';
import { Absorb2StraightConnlineSvc } from './absorb2straightconnlinesvc.js';


//边界特征
class TGaphEdgeFeature {
    constructor(graph, p1, p2, edgeKind, desc) {
        this.refGraph = graph;
        this.edgeLine = new LGXCOM.LGXRayLine();
        this.edgeLine.setPt(p1, p2);
        this.stPt = new LGXCOM.LGXPoint();
        this.stPt.clone(p1);
        this.endPt = new LGXCOM.LGXPoint();
        this.endPt.clone(p2);

        //0--水平方向，1---垂直方向//水平方向的，偏移Y值     
        this.hornVertKind = funcs.chkHornVertKind(p1, p2);
        this.edgeKind = edgeKind;//0---图形边界 ，1---图形中心线
        this.desc = desc;
    }
}

//图形特征
class TGraphFeature {
    constructor(graph) {
        this.refGraph = graph;
        this.featurePtLst = new Array();//特征点列表，世界坐标
        this.width = 0;//宽度
        this.height = 0;
        this.edgeFeatureList = new Array();//图形四个边界的向量，世界坐标系
    }
}

var TezhengBuzhuoSvc = {}



TezhengBuzhuoSvc.absorbMouse2OtherGraphFeature = function (pDataMng, mousePoint, originOffsetPt,inDragProcessing) {
    if (GlobalVar.editMode != "viso") {
        return null;
    }
    if (pDataMng.getMapWorkMode() != LGXEnums.LGXWorkMode.ModifyMode) {
        return null;
    }
    var pCurentGraph = pDataMng.getCurentGraph();
    if (!pCurentGraph || (pCurentGraph && pCurentGraph.getModifing() != 1)) {
        return null;
    }
    if (funcs.isDimGraph(pCurentGraph.getType())) {
        return null;
    }

    let translateFlag = true;
    if (pCurentGraph) {
        translateFlag = pCurentGraph.chkInTranslating();
    }
    // console.log("pCurentGraph.getSelKind():" + pCurentGraph.getSelKind());

    //边界对齐吸附
    let edDdgeAbsorbResult = this.absorbMousePos2SurroundGraph(pDataMng, pCurentGraph, mousePoint, originOffsetPt, translateFlag);

    //连接线
    let crossConnLineAbsorbResult = null;
    if (pCurentGraph
        && pCurentGraph.m_graphType != LGXEnums.LGXGraphType.LineGraph_type
        && pCurentGraph.getTopoRes()) {
        let absorbFuncs = Absorb2StraightConnlineSvc.absorbMousePos2StraightConnLineBetweenCurentGraph;
        crossConnLineAbsorbResult = absorbFuncs(pCurentGraph, mousePoint, originOffsetPt,inDragProcessing);
    }

    let destAborbResult = null;
    if (edDdgeAbsorbResult && !crossConnLineAbsorbResult){
        destAborbResult = edDdgeAbsorbResult;
    }
    else if (!edDdgeAbsorbResult && crossConnLineAbsorbResult){
        destAborbResult = crossConnLineAbsorbResult;
    }
    if (edDdgeAbsorbResult && crossConnLineAbsorbResult){
        destAborbResult = this.getNearestResult(edDdgeAbsorbResult,crossConnLineAbsorbResult);//取偏移最小的为目标吸附结果，
    }

    return destAborbResult;
}

TezhengBuzhuoSvc.absorbMousePos2SurroundGraph = function (pDataMng, pCurentGraph,
    mousePoint, originOffsetPt, translateFlag) {
    var disFlag = 0;
    //获取当前被编辑图形的特征点和相对于当前鼠标的偏移队列
    //当前图形可能是正在被拖动的，也可能是将要绘制，但是还没有启动绘制的
    var curentFeature = this.getGraphTransFeature(pCurentGraph, mousePoint);
    if (!curentFeature || (curentFeature && curentFeature.edgeFeatureList.length == 0)) {
        return null;
    }
    var destPoint = new LGXCOM.LGXPoint();//找到可以对齐的目标点

    var offsetPoint = new LGXCOM.LGXPoint();//找到可以对齐的目标点

    var hornMinDis = -1;
    let hornAbortDstEge = null;
    let curentHornEdge = null;

    var vertMinDis = -1;
    let vertAbortDstEge = null;
    let curentVertEdge = null;

    let xabsorb = false;
    let yabsorb = false;

    for (var i = 0; i < curentFeature.edgeFeatureList.length; i++) {
        let edgeFeature = curentFeature.edgeFeatureList[i];
        if (!this.chkEdgeNeedAbsorb(pCurentGraph, edgeFeature)) {
            continue;
        }
        var result = this.absorb2OtherEdge(pDataMng, edgeFeature, pCurentGraph, mousePoint, originOffsetPt, translateFlag);
        if (result.abortDstEge) {
            if (edgeFeature.hornVertKind == 1) {
                if (hornMinDis < 0) {
                    hornMinDis = result.dis;
                    hornAbortDstEge = result.abortDstEge;
                    curentHornEdge = edgeFeature;
                }
                else if (hornMinDis > result.dis) {
                    hornMinDis = result.dis;
                    hornAbortDstEge = result.abortDstEge;
                    curentHornEdge = edgeFeature;
                }
            }
            else if (edgeFeature.hornVertKind == 2) {
                if (vertMinDis < 0) {
                    vertMinDis = result.dis;
                    vertAbortDstEge = result.abortDstEge;
                    curentVertEdge = edgeFeature;
                }
                else if (vertMinDis > result.dis) {
                    vertMinDis = result.dis;
                    vertAbortDstEge = result.abortDstEge;
                    curentVertEdge = edgeFeature;
                }
            }
        }
    }

    let auxDataMng = pDataMng.getAuxDataManager();
    if (!hornAbortDstEge) {
        //如果水平边界没找到可对齐的，则隐藏纵向对齐吸附参考线
        auxDataMng.resetProcessingEdgeDirLine(mousePoint, destPoint, 2, 2, null, null);
        var ptemp = pDataMng.getXLastAbsorbGraph();
        if (ptemp && ptemp.getUseful() == 1) {
            pDataMng.recordRefreshScope(ptemp.getZone());
        }

        let graphZoneLst = pDataMng.setAbsorbRayLine(2, null);
        for (i = 0; i < graphZoneLst.lenth; i++) {
            var rect = graphZoneLst[i];
            pDataMng.recordRefreshScope(rect);
        }
    }
    else {
        let guideLine = this.calGuideLine(curentHornEdge, hornAbortDstEge);
        let parallelRay1 = null;
        let parallelRay2 = null;
        if (curentHornEdge.edgeKind == hornAbortDstEge.edgeKind) {
            let parallelWidth = 0;
            let dirVct1 = new LGXCOM.LGXVector();
            let dirVct2 = new LGXCOM.LGXVector();
            let offset1 = 0;
            let offset2 = 0;
            let curentZone = curentHornEdge.refGraph.getZone();
            let graph1 = hornAbortDstEge.refGraph;
            let localZone1 = graph1.getLocalZoneInWorld();
            let graph2 = curentHornEdge.refGraph;
            let localZone2 = graph2.getLocalZoneInWorld();
            if (Math.abs(localZone1.height() - localZone2.height()) < global.ZERO_4E) {
                parallelWidth = localZone1.height();
                if (curentHornEdge.edgeKind == "top") {
                    dirVct1.m = 0;
                    dirVct1.n = 1;
                    offset1 = parallelWidth / 2;

                    dirVct2.m = 0;
                    dirVct2.n = 1;
                    offset2 = parallelWidth;
                }
                else if (curentHornEdge.edgeKind == "bottom") {
                    dirVct1.m = 0;
                    dirVct1.n = -1;
                    offset1 = parallelWidth / 2;

                    dirVct2.m = 0;
                    dirVct2.n = -1;
                    offset2 = parallelWidth;
                }
                else if (curentHornEdge.edgeKind == "vert_mid") {
                    dirVct1.m = 0;
                    dirVct1.n = 1;
                    offset1 = parallelWidth / 2;

                    dirVct2.m = 0;
                    dirVct2.n = -1;
                    offset2 = parallelWidth / 2;
                }
                parallelRay1 = { dir: dirVct1, offset: offset1 };
                parallelRay2 = { dir: dirVct2, offset: offset2 };
            }
        }
        auxDataMng.resetProcessingEdgeDirLine(guideLine.stPt, guideLine.endPt, 2, 1, parallelRay1, parallelRay2);

        let graphZoneLst = pDataMng.setAbsorbRayLine(2, hornAbortDstEge.refGraph);
        for (let i = 0; i < graphZoneLst.lenth; i++) {
            var rect = graphZoneLst[i];
            pDataMng.recordRefreshScope(rect);
        }
        let dy = hornAbortDstEge.edgeLine.stPt.y - curentHornEdge.edgeLine.stPt.y;
        offsetPoint.y = dy;
        yabsorb = true;
        disFlag++;
    }

    if (!vertAbortDstEge) {
        auxDataMng.resetProcessingEdgeDirLine(mousePoint, destPoint, 1, 2, null, null);
        let ptemp = pDataMng.getYLastAbsorbGraph();
        if (ptemp && ptemp.getUseful() == 1) {
            pDataMng.recordRefreshScope(ptemp.getZone());
        }

        let graphZoneLst = pDataMng.setAbsorbRayLine(1, null);
        for (let i = 0; i < graphZoneLst.length; i++) {
            let rect = graphZoneLst[i];
            pDataMng.recordRefreshScope(rect);
        }
    }
    else {
        let parallelRay1 = null;
        let parallelRay2 = null;
        if (curentVertEdge.edgeKind == vertAbortDstEge.edgeKind) {
            let parallelWidth = 0;
            let dirVct1 = new LGXCOM.LGXVector();
            let dirVct2 = new LGXCOM.LGXVector();
            let offset1 = 0;
            let offset2 = 0;
            let curentZone = curentVertEdge.refGraph.getZone();
            let graph1 = vertAbortDstEge.refGraph;
            let localZone1 = graph1.getLocalZoneInWorld();
            let graph2 = curentVertEdge.refGraph;
            let localZone2 = graph2.getLocalZoneInWorld();
            if (Math.abs(localZone1.width() - localZone2.width()) < global.ZERO_4E) {
                parallelWidth = localZone1.width();
                if (curentVertEdge.edgeKind == "left") {
                    dirVct1.m = 1;
                    dirVct1.n = 0;
                    offset1 = parallelWidth / 2;

                    dirVct2.m = 1;
                    dirVct2.n = 0;
                    offset2 = parallelWidth;
                }
                else if (curentVertEdge.edgeKind == "right") {
                    dirVct1.m = -1;
                    dirVct1.n = 0;
                    offset1 = parallelWidth / 2;

                    dirVct2.m = -1;
                    dirVct2.n = 0;
                    offset2 = parallelWidth;
                }
                else if (curentVertEdge.edgeKind == "horn_mid") {
                    dirVct1.m = 1;
                    dirVct1.n = 0;
                    offset1 = parallelWidth / 2;

                    dirVct2.m = -1;
                    dirVct2.n = 0;
                    offset2 = parallelWidth / 2;
                }
                parallelRay1 = { dir: dirVct1, offset: offset1 };
                parallelRay2 = { dir: dirVct2, offset: offset2 };
            }
        }
        let guideLine = this.calGuideLine(curentVertEdge, vertAbortDstEge);
        auxDataMng.resetProcessingEdgeDirLine(guideLine.stPt, guideLine.endPt, 1, 1, parallelRay1, parallelRay2);
        let graphZoneLst = pDataMng.setAbsorbRayLine(1, vertAbortDstEge.refGraph);
        for (let i = 0; i < graphZoneLst.lenth; i++) {
            var rect = graphZoneLst[i];
            pDataMng.recordRefreshScope(rect);
        }
        let dx = vertAbortDstEge.edgeLine.stPt.x - curentVertEdge.edgeLine.stPt.x;
        offsetPoint.x = dx;
        xabsorb = true;
        disFlag++;
    }
    if (disFlag) {
        return { offset: offsetPoint, xabsorb, yabsorb };
    }
    else {
        return null;
    }
}

TezhengBuzhuoSvc.calGuideLine = function (curentEdge, absorbEdge) {
    let p3 = curentEdge.stPt;
    let p4 = curentEdge.endPt;

    let p1 = absorbEdge.stPt;
    let p2 = absorbEdge.endPt;

    let dis1 = funcs.distancePoint(p1, p3, 1);
    let dis2 = funcs.distancePoint(p1, p4, 1);
    let dis3 = funcs.distancePoint(p2, p3, 1);
    let dis4 = funcs.distancePoint(p2, p4, 1);

    let stPt = p1;
    let farestPt = p3;
    let maxDis = dis1;
    let guideLnDir = new LGXCOM.LGXVector();
    guideLnDir.setBy2Pt(stPt, p2);

    if (dis1 < dis2) {
        farestPt = p4;
        maxDis = dis2;
    }

    if (maxDis < dis3) {
        stPt = p2;
        farestPt = p3;
        maxDis = dis3;
        guideLnDir.setBy2Pt(stPt, p1);
    }

    if (maxDis < dis4) {
        stPt = p2;
        farestPt = p4;
        guideLnDir.setBy2Pt(stPt, p1);
    }

    let lenth = maxDis;
    let midPt = { x: 0, y: 0 };
    midPt.x = stPt.x + 0.5 * lenth * guideLnDir.m;
    midPt.y = stPt.y + 0.5 * lenth * guideLnDir.n;

    stPt.x = midPt.x - lenth * guideLnDir.m;
    stPt.y = midPt.y - lenth * guideLnDir.n;

    let endPt = { x: 0, y: 0 };
    endPt.x = midPt.x + lenth * guideLnDir.m;
    endPt.y = midPt.y + lenth * guideLnDir.n;

    let guideLine = { stPt, endPt };
    return guideLine;
}

//获取当前被编辑图形的特征点和相对于当前鼠标的偏移队列
//当前图形可能是正在被拖动的，也可能是将要绘制，但是还没有启动绘制的
//计算移动时图形的特征点坐标ptlst和每个特征的相对于起始移动坐标点的偏移队列offsetlst
TezhengBuzhuoSvc.getGraphTransFeature = function (graph, mousePoint) {
    if (!graph) {
        return null;
    }
    let graphFeature = new TGraphFeature(graph);
    let symScope = graph.getLocalZoneInWorld();
    graphFeature.width = symScope.width();
    graphFeature.height = symScope.height();

    //边界特征
    var rotv = graph.getRadAngle();
    var rotcnt = symScope.getCnt();

    if (graph.m_graphType != LGXEnums.LGXGraphType.LineGraph_type) {
        var lefttopPt = { x: symScope.left, y: symScope.top };
        var p1 = funcs.rotate(lefttopPt, rotcnt, rotv);

        var righttopPt = { x: symScope.right, y: symScope.top };
        var p2 = funcs.rotate(righttopPt, rotcnt, rotv);

        var rightBotPt = { x: symScope.right, y: symScope.bottom };
        var p3 = funcs.rotate(rightBotPt, rotcnt, rotv);

        var leftBotPt = { x: symScope.left, y: symScope.bottom };
        var p4 = funcs.rotate(leftBotPt, rotcnt, rotv);


        let topEdge = new TGaphEdgeFeature(graph, p1, p2, 0, 'top');
        graphFeature.edgeFeatureList.push(topEdge);

        let rightEdge = new TGaphEdgeFeature(graph, p2, p3, 0, 'right');
        graphFeature.edgeFeatureList.push(rightEdge);

        let bottomEdge = new TGaphEdgeFeature(graph, p3, p4, 0, 'bottom');
        graphFeature.edgeFeatureList.push(bottomEdge);

        let leftEdge = new TGaphEdgeFeature(graph, p4, p1, 0, 'left');
        graphFeature.edgeFeatureList.push(leftEdge);

        // //垂直中心线
        var topMidPt = { x: (lefttopPt.x + righttopPt.x) / 2.0, y: (lefttopPt.y + righttopPt.y) / 2.0 };
        let vertMidEdge = new TGaphEdgeFeature(graph, rotcnt, topMidPt, 1, 'vert_mid');
        graphFeature.edgeFeatureList.push(vertMidEdge);

        // //水平中心线右边点
        var rightMidPt = { x: (rightBotPt.x + righttopPt.x) / 2.0, y: (rightBotPt.y + righttopPt.y) / 2.0 };
        let hornMidEdge = new TGaphEdgeFeature(graph, rotcnt, rightMidPt, 1, 'horn_mid');
        graphFeature.edgeFeatureList.push(hornMidEdge);
    }
    else {
        //线路对象，还需要把横平竖直的线段也作为特征
        let position = graph.getPosCopy();
        let ptlist = position.posList;
        if (ptlist.length < 2) {
            return null;
        }
        let prePt = ptlist[0];
        for (let i = 1; i < ptlist.length; i++) {
            let nextPt = ptlist[i];
            let vect = funcs.getVector(prePt, nextPt);
            if (vect.getHornVertKind() != 0) {
                let otherEdge = new TGaphEdgeFeature(graph, prePt, nextPt, 0, 'other');
                graphFeature.edgeFeatureList.push(otherEdge);
            }
            prePt = nextPt;
        }

    }
    return graphFeature;
}

TezhengBuzhuoSvc.absorb2OtherEdge = function (pDataMng, edgeFeature, pCurentGraph, mousePoint, originOffsetPt, translateFlag) {
    let scaling = pDataMng.getScaling();
    var minDis = -1;
    let abortDstEge = null;
    var graphLst = pDataMng.getAllGraphs();
    var count = graphLst.length;
    for (let i = 0; i < count; i++) {
        let pGraph = graphLst[i];
        if (!this.chkCanAbsorb(pCurentGraph, pGraph)) {
            continue;
        }

        var feature = this.getGraphTransFeature(pGraph, mousePoint);
        if (!feature) {
            continue;
        }
        for (var n = 0; n < feature.edgeFeatureList.length; n++) {
            let tempEdge = feature.edgeFeatureList[n];
            if (!this.chkEdgeNeedAbsorb(pCurentGraph, tempEdge)) {
                continue;
            }
            let chkRst = this.chkMayAlgin(edgeFeature, tempEdge, scaling, translateFlag);
            if (chkRst.flag && !this.chkIsFarApart(edgeFeature, tempEdge, originOffsetPt)) {
                //如果是拉开的，两个边界越来越远的，也不用吸附，靠近才需要
                //否则会导致吸附后无法分开
                if (minDis < 0) {
                    minDis = chkRst.dis;
                    abortDstEge = tempEdge;
                }
                else if (minDis > chkRst.dis) {
                    minDis = chkRst.dis;
                    abortDstEge = tempEdge;
                }
            }
        }
    }

    var rst = { abortDstEge, dis: minDis };
    return rst;
}

TezhengBuzhuoSvc.chkCanAbsorb = function (pCurentGraph, pGraph) {
    let flag = true;
    let group = funcs.group(pGraph.getType());
    let childList = pCurentGraph.getAllChild();
    if (pCurentGraph == pGraph
        || pGraph.getFinish() == 0
        || pGraph.getUseful() != 1
        || pGraph.getModifing() == 1
        || pGraph == pCurentGraph.getLabel()
        || group == global.dimGroup
        || pCurentGraph.m_graphType == LGXEnums.LGXGraphType.FastToolPanel_type
        || pGraph.m_graphType == LGXEnums.LGXGraphType.DimTextGraph_type
        || childList.indexOf(pGraph) >= 0
    ) {
        return false;
    }

    if (pGraph.m_graphType == LGXEnums.LGXGraphType.TextGraph_type
        && pCurentGraph == pGraph.getParentGraph()) {
        return false;
    }

    if ((pGraph.m_graphType == LGXEnums.LGXGraphType.TextGraph_type
        && pCurentGraph.m_graphType != LGXEnums.LGXGraphType.TextGraph_type)
        || (pGraph.m_graphType != LGXEnums.LGXGraphType.TextGraph_type
            && pCurentGraph.m_graphType == LGXEnums.LGXGraphType.TextGraph_type)) {
        return false;
    }

    if (pGraph.m_graphType == LGXEnums.LGXGraphType.LineGraph_type && pGraph.m_topoRes) {
        let tNodeList = pGraph.m_topoRes.m_connNodeList;
        for (let i = 0; i < tNodeList.length; i++) {
            let node = tNodeList[i];
            if (node.m_refRes && node.m_refRes == pCurentGraph.m_topoRes) {
                return false;
            }
        }
    }

    if (pGraph.m_graphType == LGXEnums.LGXGraphType.LineGraph_type) {
        flag = pGraph.chkAllSecHornVertical();
    }

    if (flag) {
        if (funcs.isBaseUnit(pGraph.getType()) && pGraph.getContainer()) {
            flag = false;
        }
    }

    return flag;
}

TezhengBuzhuoSvc.chkMayAlgin = function (srcEdge, dstEdge, scaling, translateFlag) {
    let canNotAlginRst = { flag: false, dis: -1 };
    if (//srcEdge.edgeKind != dstEdge.edgeKind
        Math.abs(srcEdge.hornVertKind - dstEdge.hornVertKind) > global.ZERO_4E) {
        return canNotAlginRst;
    }

    let flag = false;
    let dis = funcs.pointToRayLineDistance(srcEdge.edgeLine.stPt, dstEdge.edgeLine);
    if (!translateFlag) {
        //变形修改情况下，已对齐的边不再判断
        if (dis < global.ZERO_4E) {
            return canNotAlginRst;
        }
    }
    let absorbDis = global.SelectGap / scaling;
    if (dis < absorbDis) {
        flag = true;
    }
    return { flag, dis };
}

TezhengBuzhuoSvc.chkIsFarApart = function (srcEdge, dstEdge, originOffsetPt) {
    let flag = false;
    //移动前两者间距
    let preDis = funcs.pointToRayLineDistance(srcEdge.edgeLine.stPt, dstEdge.edgeLine);

    //移动后两者
    let x = srcEdge.edgeLine.stPt.x + originOffsetPt.x;
    let y = srcEdge.edgeLine.stPt.y + originOffsetPt.y;
    let nextDis = funcs.pointToRayLineDistance({ x, y }, dstEdge.edgeLine);
    if (nextDis > preDis) {
        flag = true;
    }
    return flag;
}

//如果特征点和目标点都在同一个图形上，则此次吸附无效，继续检测下一个
TezhengBuzhuoSvc.chkFeaturePtAndDstPtOnSameGraph = function (pDstAbsorbGraph, featurePt, destPoint) {
    var flag = false;
    var rect = pDstAbsorbGraph.getZone();
    if (rect.contains(featurePt.x, featurePt.y) && rect.contains(destPoint.x, destPoint.y)) {
        flag = true;
    }
    return flag;
}

TezhengBuzhuoSvc.chkEdgeNeedAbsorb = function (pCurentGraph, edgeInfo) {
    let flag = true;
    let selKind = pCurentGraph.getSelKind();
    switch (selKind) {
        case LGXEnums.LGXModGraphKind.Drag_TopMid:
        case LGXEnums.LGXModGraphKind.Drag_BottomMid:
            //拖拽上下边线，只能上下拖，这时候只需要吸附水平方向的特征边界
            if (edgeInfo.hornVertKind != 1) {
                flag = false;
            }
            break;

        case LGXEnums.LGXModGraphKind.Drag_RightMid:
        case LGXEnums.LGXModGraphKind.Drag_LeftMid:
            //拖拽左右边线，只能左右拖，这时候只需要吸附垂直方向的特征边界
            if (edgeInfo.hornVertKind != 2) {
                flag = false;
            }
            break;

        default:
            break;
    }
    return flag;
}

//取偏移最小的为目标吸附结果，
TezhengBuzhuoSvc.getNearestResult = function(absorbResult1,absorbResult2){
    let p0 = {x:0,y:0};
    let dis1 = funcs.distancePoint(absorbResult1.offset,p0,1);
    let dis2 = funcs.distancePoint(absorbResult2.offset,p0,1);
    let ret = absorbResult1;
    if (dis1 > dis2){
        ret = absorbResult2;
    }
    return ret;
}


export default { TezhengBuzhuoSvc, TGraphFeature, TGaphEdgeFeature }


